package tools

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

// BytesEqual 比较两个字节切片是否相等
func BytesEqual(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// ByteContain 判断 data 是否包含 prefix
// 如果存在返回第一次匹配的索引值, 如果不存在返回 -1
func ByteContain(data []byte, prefix []byte) int {
	prefixLen := len(prefix)
	dataLen := len(data)
	if prefixLen > dataLen {
		return -2 // 前缀长度超过数据长度，不可能找到匹配项
	}
	for i := 0; i <= dataLen-prefixLen; i++ {
		if BytesEqual(data[i:i+prefixLen], prefix) {
			return i // 返回匹配的位置
		}
	}
	return -1 // 没有找到匹配的位置
}

// MatchSuffix 判断 suffix 是否能和 data 结尾衔接, 找到最长重叠部分的起始索引
func MatchSuffix(data []byte, suffix []byte) (index int, b bool) {
	b = false
	index = -1
	var len1 = len(data)
	var len2 = len(suffix)
	if len1 < len2 {
		return
	}

	for i := 1; i < len2; i++ {
		if BytesEqual(suffix[0:i], data[len1-i:]) {
			b = true
			index = len1 - i
		}
	}
	return
}

// ByteToBinaryString 将一个 byte 转换成8位的二进制字符串。
func ByteToBinaryString(b byte) string {
	binaryString := ""
	for i := 7; i >= 0; i-- { // 从最高位到最低位
		if (b & (1 << i)) != 0 {
			binaryString += "1"
		} else {
			binaryString += "0"
		}
	}
	return binaryString
}

func Uint16ToBinaryString(b uint16) string {
	binaryString := ""
	for i := 15; i >= 0; i-- { // 从最高位到最低位
		if (b & (1 << i)) != 0 {
			binaryString += "1"
		} else {
			binaryString += "0"
		}
	}
	return binaryString
}

func BinaryStringToArray(str string) (res []int) {
	for i := 0; i < len(str); i++ {
		s := string([]byte{str[i]})
		v, _ := strconv.Atoi(s)
		res = append(res, v)
	}
	return
}

// BinaryStringToByte 将一个8位二进制字符串转换成一个byte
func BinaryStringToByte(str string) (b byte, err error) {
	// 使用 strconv.ParseUint 将二进制字符串转为基数为2的整数
	value, err := strconv.ParseUint(str, 2, 8) // 8 表示最多占用8位，即一个 byte 的大小
	if err != nil {
		return 0, fmt.Errorf("invalid binary string: %v", err)
	}
	return byte(value), nil
}

// ByteToBitArray 将一个 byte 转换成8位数组。
func ByteToBitArray(b byte) [8]uint8 {
	arr := [8]uint8{}
	for i := 7; i >= 0; i-- { // 从最高位到最低位
		if (b & (1 << i)) != 0 {
			arr[8-i-1] = 1
		} else {
			arr[8-i-1] = 0
		}
	}
	return arr
}

// ByteToHexStr 将一个 byte 转换成十六进制字符串
func ByteToHexStr(b byte) string {
	return strings.ToUpper(fmt.Sprintf("%02x", b))
}

// ByteArrayToHexStr 字节数组转16进制字符串
func ByteArrayToHexStr(b []byte) string {
	str := ""
	for i := 0; i < len(b); i++ {
		twoDigitHexStr := fmt.Sprintf("%02x", b[i])
		str = str + twoDigitHexStr
	}
	return strings.ToUpper(str)
}

// HexToInt64 16进制字符串转10进制 todo
func HexToInt64(hexStr string) (int64, error) {
	decimal, err := strconv.ParseInt(hexStr, 16, 64)
	if err != nil {
		return 0, err
	}
	return decimal, nil
}

// Int64ToHexStr 整型转16进制字符串 todo
func Int64ToHexStr(n int64) string {
	return fmt.Sprintf("%X\n", n)
}

// HexStrToByteArray 16进制字符串转byte数组
func HexStrToByteArray(hexStr string) (byteArr []byte, err error) {
	byteArr, err = hex.DecodeString(hexStr)
	if err != nil {
		return
	}
	return
}

// HexStrToByte 16进制字符串转byte
func HexStrToByte(hexStr string) (b byte, err error) {
	if len(hexStr) != 2 {
		err = errors.New("16进制转byte失败:" + hexStr)
	}
	byteArr, err := hex.DecodeString(hexStr)
	if err != nil {
		return
	}
	if len(byteArr) != 1 {
		err = errors.New("16进制转byte失败:" + hexStr)
	}
	b = byteArr[0]
	return
}

// HexStrToUint16 16进制字符串转uint16
func HexStrToUint16(hexStr string) (n uint16, err error) {
	if len(hexStr) != 4 {
		err = errors.New("16进制转uint16失败:" + hexStr)
	}
	byteArr, err := hex.DecodeString(hexStr)
	if err != nil {
		return
	}
	if len(byteArr) != 2 {
		err = errors.New("16进制转uint16失败:" + hexStr)
	}
	n = BytesToUint16(byteArr, "big")
	return
}

// BytesToUint32 byte数组转uint32
func BytesToUint32(data []byte, endian string) uint32 {
	if len(data) > 4 || len(data) == 0 {
		return 0
	}
	var value uint32
	reader := bytes.NewReader(data)
	if endian == "big" || endian == "" {
		_ = binary.Read(reader, binary.BigEndian, &value)
	} else {
		_ = binary.Read(reader, binary.LittleEndian, &value)
	}
	return value
}

// BytesToUint16 byte数组转uint16
func BytesToUint16(data []byte, endian string) uint16 {
	if len(data) != 2 {
		return 0
	}
	var value uint16
	reader := bytes.NewReader(data)
	if endian == "big" || endian == "" {
		_ = binary.Read(reader, binary.BigEndian, &value)
	} else {
		_ = binary.Read(reader, binary.LittleEndian, &value)
	}
	return value
}

// Uint32ToBytes uint32 转换为 [4]byte
func Uint32ToBytes(n uint32, endian string) [4]byte {
	var byteLen [4]byte
	if endian == "big" || endian == "" {
		// 使用 PutUint 方法将 uint 转换为字节切片，并指定大端字节序
		binary.BigEndian.PutUint32(byteLen[:], n)
	} else {
		binary.LittleEndian.PutUint32(byteLen[:], n)
	}
	return byteLen
}

// Uint64ToBytes uint64 转换为 [4]byte
func Uint64ToBytes(n uint64, endian string) [8]byte {
	var byteLen [8]byte
	if endian == "big" || endian == "" {
		// 使用 PutUint 方法将 uint 转换为字节切片，并指定大端字节序
		binary.BigEndian.PutUint64(byteLen[:], n)
	} else {
		binary.LittleEndian.PutUint64(byteLen[:], n)
	}
	return byteLen
}

// Uint32ToHexStr uint32 转换为十六进制字符串
func Uint32ToHexStr(n uint32, endian string) string {
	b := Uint32ToBytes(n, endian)
	return ByteArrayToHexStr(b[0:])
}

// Uint16ToBytes uint16 转换为 [2]byte
func Uint16ToBytes(n uint16, endian string) [2]byte {
	var byteLen [2]byte
	if endian == "big" || endian == "" {
		// 使用 PutUint 方法将 uint 转换为字节切片，并指定大端字节序
		binary.BigEndian.PutUint16(byteLen[:], n)
	} else {
		binary.LittleEndian.PutUint16(byteLen[:], n)
	}
	return byteLen
}

// Uint16ToHexStr uint16 转换为十六进制字符串
func Uint16ToHexStr(n uint16, endian string) string {
	b := Uint16ToBytes(n, endian)
	return ByteArrayToHexStr(b[0:])
}

// Float32ToHexStr float32转十六进制字符串
func Float32ToHexStr(f float32, endian string) string {
	var b []byte
	if endian == "little" || endian == "" {
		b = Float32ToBytes(f, "little")
	} else {
		b = Float32ToBytes(f, "big")
	}
	hexStr := ByteArrayToHexStr(b)
	return strings.ToUpper(hexStr)
}

// Float64ToHexStr float654转十六进制字符串
func Float64ToHexStr(f float64, endian string) string {
	var b []byte
	if endian == "little" || endian == "" {
		b = Float64ToBytes(f, "little")
	} else {
		b = Float64ToBytes(f, "big")
	}
	hexStr := ByteArrayToHexStr(b)
	return strings.ToUpper(hexStr)
}

// ValidateHexStr 判断十六进制字符串是否有效, 并返回 []byte 长度
func ValidateHexStr(str string) (n int, err error) {
	if str == "" {
		return
	}
	byteArr, err := HexStrToByteArray(str)
	if err != nil {
		return 0, err
	}
	return len(byteArr), nil
}

// Float32ToBytes float32转[]byte
func Float32ToBytes(float float32, endian string) []byte {
	bits := math.Float32bits(float)
	b := make([]byte, 4)
	if endian == "little" || endian == "" {
		binary.LittleEndian.PutUint32(b, bits)
	} else {
		binary.BigEndian.PutUint32(b, bits)
	}
	return b
}

// Float32ToBytes4 float32转[4]byte
func Float32ToBytes4(float float32, endian string) [4]byte {
	bits := math.Float32bits(float)
	b := make([]byte, 4)
	var b4 [4]byte
	if endian == "little" || endian == "" {
		binary.LittleEndian.PutUint32(b, bits)
	} else {
		binary.BigEndian.PutUint32(b, bits)
	}
	for i := 0; i < 4; i++ {
		b4[i] = b[i]
	}
	return b4
}

// BytesToFloat32 []byte转float32
func BytesToFloat32(bytes []byte, endian string) float32 {
	var bits uint32
	if endian == "little" || endian == "" {
		bits = binary.LittleEndian.Uint32(bytes)
	} else {
		bits = binary.BigEndian.Uint32(bytes)
	}
	//fmt.Println("")
	return math.Float32frombits(bits)
}

// Float64ToBytes float64转[]byte
func Float64ToBytes(float float64, endian string) []byte {
	bits := math.Float64bits(float)
	b := make([]byte, 8)
	if endian == "little" || endian == "" {
		binary.LittleEndian.PutUint64(b, bits)
	} else {
		binary.BigEndian.PutUint64(b, bits)
	}
	return b
}

// BytesToFloat64 []byte转float64
func BytesToFloat64(bytes []byte, endian string) float64 {
	var bits uint64
	if endian == "little" || endian == "" {
		bits = binary.LittleEndian.Uint64(bytes)
	} else {
		bits = binary.BigEndian.Uint64(bytes)
	}
	return math.Float64frombits(bits)
}

// ValidateHexAndLen 验证十六进制字符串长度, 并返回 []byte
func ValidateHexAndLen(hexStr string, length int) (byteArr []byte, err error) {
	byteArr, err = HexStrToByteArray(hexStr)
	if err != nil {
		err = errors.New(fmt.Sprintf("无效的十六进制字符串"))
		return
	}
	if length != len(byteArr) {
		err = errors.New(fmt.Sprintf("字节长度不匹配"))
		return
	}
	return
}

// BytesPaddingLeft 不满n字节左侧填充0
func BytesPaddingLeft(data []byte, length int) []byte {
	if len(data) < length {
		padding := make([]byte, length-len(data))
		data = append(padding, data...)
	}
	return data
}

// BytesRemoveLeft 删除左侧多余字节, 实际场景只有uint类型大端模式且字节占用非标准长度时才会使用
func BytesRemoveLeft(data []byte, realLength int) []byte {
	if len(data) > realLength {
		// 截取需要的实际长度
		data = data[len(data)-realLength:]
	} else if len(data) < realLength {
		// 不足实际长度的补0
		data = BytesPaddingLeft(data, realLength)
	}
	return data
}

func StringReverse(str string) string {
	arr := []byte(str)
	for i, j := 0, len(str)-1; i < j; i, j = i+1, j-1 {
		arr[i], arr[j] = arr[j], arr[i]
	}
	return string(arr)
}

func Uint16BitsToUint8(data uint16, startBit, endBit int, endian string) (value uint8, err error) {
	if startBit > endBit {
		err = errors.New("开始位大于结束位")
		return
	}
	str := Uint16ToBinaryString(data)
	//fmt.Printf("str --- %s\n", str)
	str = StringReverse(str)
	part := SubStr(str, startBit, endBit-startBit+1)
	part = StringReverse(part)
	//fmt.Printf("part--- %s\n", part)
	if len(part) > 8 {
		err = errors.New("位长度超出8位")
		return
	}
	if len(part) < 8 {
		part = strings.Repeat("0", 8-len(part)) + part
	}
	value, err = BinaryStringToByte(part)
	return
}
